/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package sopra09.lv6659438.logik.eintragErfassen;

import java.util.Set;
import javax.annotation.Resource;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;
import javax.interceptor.Interceptors;
import javax.persistence.EntityExistsException;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import sopra09.lv6659438.objekte.Zeitschrift;
import sopra09.lv6659438.logik.awfUnabhaengigeKomponenten.LoggingInterceptor;
import sopra09.lv6659438.objekte.Autor;
import sopra09.lv6659438.objekte.Buch;


/**
 * Verarbeitet neue Literatureinträge.
 * @author TJ
 */
@Stateless
@Interceptors({LoggingInterceptor.class, EintragErfassenInterceptor.class})
public class EintragErfassenALBean implements EintragErfassenALLocal {
    @PersistenceContext
    private EntityManager em;
    @Resource SessionContext ctx;
   
    /**
     * Übergibt ein neues mit den Eingabeparametern gefülltes Zeitschrift-Objekt
     * zum Persistieren.
     * @param titel
     * @param nummer
     * @param volumen
     * @return true bei erfolgreicher Persitierung, sonst false
     */
    public boolean verarbeiteZeitschrift(String titel, int nummer, int volumen) {

        Zeitschrift zeitschrift = new Zeitschrift();
        
        zeitschrift.setTitel(titel);
        zeitschrift.setNummer(nummer);
        zeitschrift.setVolumen(volumen);

        try {
            em.persist(zeitschrift);
            return true;
        } catch (EntityExistsException e){
            ctx.setRollbackOnly();
            return false;
        }
    }

    /**
     * Liefert ein neues Buchobjekt.
     * @param titel
     * @param jahr
     * @return mit Eingabeparametern gefülltes neues Buchobjekt.
     */
    public Buch liefereNeuesBuchobjekt(String titel, int jahr) {
        Buch neuesBuch = new Buch(titel, jahr);       
        return neuesBuch;
    }

    /**
     * Verbindet und persistiert das übergebene Buch und seine Autoren
     * @param book
     * @return true, wenn Buch und Autoren erfolgreich verbunden und persistiert
     * wurden, sonst false.
     */
    public boolean erfasseBuch(Buch book) {
       Buch buch = book;
       boolean erfolgreichVerbunden;
      Set<Autor> autoren = buch.getAutoren();

      // test ob das buch autoren hat
        if (buch.getAutoren()== null) {
            return false; //Verbundenes Autoren-Objekt obligatorisch!
        }

        // testen, ob das buch im zustand new ist, dann persistieren
       if (buch.getId() != null)
            buch = getManagedBuch(buch);
        try {
           em.persist(buch);
        } catch (EntityExistsException e) {
            ctx.setRollbackOnly();
             return false;
        }

      // testen, ob die autoren im zustand new sind, dann persistieren
        for (Autor autor : autoren) {
           if (autor.getId() != null)
                 autor = getManagedAutor(autor);
           try {
                em.persist(autor);
           } catch (EntityExistsException e) {
                ctx.setRollbackOnly();
                 return false;
           }
           // buch und autoren verbinden
           erfolgreichVerbunden =
                   this.buchUndAutorVerbinden(buch, autor);
           if (!erfolgreichVerbunden)
               return false;
         }

       return true;
     }

   /**
    * Hilfsmethode zum Verbinden von Buch und Autor
    * @param buch
    * @param autor
    * @return true wenn buch und autor erfolgreich verbunden wurden, sonst false.
    */
    private boolean buchUndAutorVerbinden(Buch buch, Autor autor) {
        Buch b = getManagedBuch(buch);
        Autor a = getManagedAutor(autor);
        if (b!=null && a!=null) {
        //Bidirektionale Verbindung herstellen (beide Richtungen)
            b.getAutoren().add(a); //
            a.getBuecher().add(b); //
            return true;
        } else
            return false;
    }

    /**
     * Hilfsmethode um ein Buch im Zustand managed zu bekommen
     * @param b ein Buch
     * @return das übergebene Buch im Zustand managed
     */
   private Buch getManagedBuch(Buch b) {
        if (em.contains(b) ||b==null)
            return b;
        else
            return em.find(Buch.class, b.getId());
    }

    /**
     * Hilfsmethode um einen Autor im Zustand managed zu bekommen
     * @param a ein Autor
     * @return den übergebenen Autor im Zustand managed
     */
    private Autor getManagedAutor(Autor a) {
        if (em.contains(a) ||a==null)
            return a;
        else
            return em.find(Autor.class, a.getId());
    }

   // Implementierte, aber nicht verwendete Methoden
  /*
    private boolean buchUndAutorVerbinden(long buch, long autor) {
        Buch b = getBuch(buch,false);
        Autor a = getAutor(autor, false);
        return buchUndAutorVerbinden(b,a);
    }


     private Buch getBuch(long id, boolean mitAutorenListe) {
       Buch b = em.find(Buch.class, id);
        if (mitAutorenListe)
            b.getAutoren();
        return b;
    }

    private Autor getAutor(long id, boolean mitBuecherListe) {
       Autor a = em.find(Autor.class, id);
        if (mitBuecherListe)
            a.getBuecher();
        return a;
    }
     */

}
